import player, boat, pirates, logging, world, wind

class PirateGame(object):
    """Manages a whole game, and manages its state. Tracks game-level rules,
    turns, phases, etc.
    """
    logger = logging.getLogger('pgame.engine.PirateGame')

    _windGen = wind.WindGenerator()
    _nextWeatherChange = 1
    _nextWeather = None
    weather = None
    players = []
    turn = 0
    
    # Current game state
    (STOPPED,
     PRE_TURN,
     WAITING_PLAYERS_TURNS,
     WAITING_MY_TURN,
     EXECUTING_TURNS,
     POST_TURN) = range(6)
     
    state = STOPPED
    
    def __init__(self):
        self.ocean = world.World({}, self)
        self.playerTurns = []
    
    def doPreTurn(self):
        """
        Get the game ready for a new turn. Takes an event to set when done.
        """
        self.logger.debug('Starting pre-turn')
        self.turn += 1
        
        self.logger.debug('Updating the weather')
        if self._nextWeather is None:
            self.weather = self._windGen.getNextWind()
            self._nextWeather = self._windGen.getNextWind()
            
        if self.turn == self._nextWeatherChange:
            #Change the wind to the next one, regenerate.
            self.weather = self._nextWeather
            while self._nextWeather == self.weather:
                self._nextWeather = self._windGen.getNextWind()
                self._nextWeatherChange += 1
                
        self.logger.debug('Updating players')
        self.playerTurns = []
        for i in range(len(self.players)):
            self.playerTurns.append(self.players[i])
            self.players[i].startTurn()
            
        self.logger.debug('Pre-turn done')

        
    def doMovementPhase(self):
        """
        Used to execute the movement phase of the current turn.
        """
        self.logger.debug('Begin movement phase.')

        for p in self.players:
            p.move()

        self.logger.debug('Movement phase finished.')

        
    def tick(self, curT):
        """
        Updates the game state, based on the changes.
        """
        if self.state == self.STOPPED:
            return
        
        if self.state == self.PRE_TURN:
            self.doPreTurn()
            self.state = self.WAITING_MY_TURN
            
        elif self.state in (self.WAITING_PLAYERS_TURNS,
                            self.WAITING_MY_TURN):
            if len(self.playerTurns) == 0:
                self.state = self.EXECUTING_TURNS
        
        elif self.state == self.EXECUTING_TURNS:
            # TODO: Make this multiple calls
            #       eg. continueMovements()
            self.doMovementPhase()
            self.state = self.POST_TURN
            
        elif self.state == self.POST_TURN:
            self.doPostTurn()
            self.state = self.PRE_TURN
    
    def onPlayerFinished(self, fplayer):
        if fplayer in self.playerTurns:
            self.playerTurns.remove(fplayer)
        if len(self.playerTurns) == 0:
            self.state = self.EXECUTING_TURNS
    
    def doPostTurn(self):
        # This might be were we respond to collisions, triggers, etc.
        pass
        
    def addPlayer(self, newPlayer=None):
        """
        Adds a new player to the current game.
        """
        if self.state != self.STOPPED:
            return
    
        if newPlayer is None:
            self.logger.debug('Creating player to add...')
            newPlayer = player.Player(self, self.ocean)
        
            self.logger.debug('Creating boat, captain, and crew')
            boatClass = len(self.players) + 1
            newboat = boat.Boat('%ic' % boatClass, self.ocean, newPlayer)
            captain = pirates.Pirate()
            newboat.crew.append(captain)
            newboat.crew.extend([pirates.Pirate(captain)
                                 for i in range(5 * boatClass)])
            
            self.logger.debug('Setting money')
            newPlayer.money += 100
            
        self.logger.debug('Adding player and returning.')
        self.players.append(newPlayer)            
        return newPlayer
    
    def start(self):
        if self._nextWeather is None:
            self._nextWeather = self._windGen.getNextWind()
        self.state = self.PRE_TURN
        
    def stop(self):
        self.state = self.STOPPED
    
    def forceCollision(self, object1, object2):
        #Cannot be implemented until client-server relations are known
        pass
